from fastapi import APIRouter, Depends, Query
from sqlalchemy.orm import Session
from pprint import pprint

from common.database import get_db
from core.response import resp_200, resp_400
from core.logger import logger

from app.bill.handlers.bill_analysis_handler import BillAnalysisHandler
from app.bill.handlers.bill_instance_handler import BillInstanceHandler
from app.bill.handlers.bill_month_handler import BillMonthHandler
from app.bill.handlers.bill_event_handler import BillEventHandler
from app.celery_task.handlers.celery_task_handler import CeleryTaskHandler
from app.bill.handlers.tag_department_handler import TagDepartmentHandler
from core.security import permission_checker

from app.bill.schemas import *


router = APIRouter()



#### 账单实例信息操作 ####
@router.get('/instance/aliyun/', summary="获取阿里云实时账单信息", description="云账单-账单可视化")
async def get_bill_instance_aliyun(bill_cycle: str = Query(..., description="查询账单的账期"), user=Depends(permission_checker)):
    bill_instance_handler = BillInstanceHandler()
    result = bill_instance_handler.get_instance_aliyun(bill_cycle)
    if not result:
        message = "get instance aliyun failed"
        logger.error(f"{message} => bill_cycle:{bill_cycle}")
        return resp_400(message)
    return resp_200(result)


@router.get('/instance/bill_cycle/', summary="获取数据库里面有哪些账期", description="云账单-账单可视化")
async def get_bill_instance_bill_cycle(page: int = Query(1, ge=1), per_page: int = Query(10, ge=0),
                              db: Session = Depends(get_db), user=Depends(permission_checker)):
    bill_instance_handler = BillInstanceHandler()
    result = bill_instance_handler.get_instance_bill_cycle(db, page, per_page)
    if not result:
        message = "get instance bill cycle failed"
        logger.error(f"{message} => page:{page} per_page:{per_page}")
        return resp_400(message)
    return resp_200(result)



@router.get('/instance/', summary="获取账单数据, 根据表字段-模糊匹配", description="云账单-账单可视化")
async def get_bill_instance_search(bill_cycle: str = Query(..., description="账期"), field: str = Query("all"), value: str = Query(""),
                               page: int = Query(1, ge=1), per_page: int = Query(10, ge=0),
                               db: Session = Depends(get_db), user=Depends(permission_checker)):
    bill_instance_handler = BillInstanceHandler()
    result = bill_instance_handler.get_instance_search(db, bill_cycle, page, per_page, field, value)
    if not result:
        message = "get instance search failed"
        logger.error(f"{message} => bill_cycle:{bill_cycle} page:{page} per_page:{per_page} field:{field} value:{value}")
        return resp_400(message)
    return resp_200(result)



@router.get('/instance/match/', summary="获取账单数据, 根据表字段-完全匹配", description="云账单-账单可视化")
async def get_bill_instance_match(bill_cycle: str = Query(..., description="账期"),
                             field: str = Query(..., description="查询的字段"), value: str = Query(..., description="查询的值"),
                             page: int = Query(1, ge=1), per_page: int = Query(10, ge=0),
                             db: Session = Depends(get_db), user=Depends(permission_checker)):
    bill_instance_handler = BillInstanceHandler()
    result = bill_instance_handler.get_instance_match(db, bill_cycle, page, per_page, field, value)
    if not result:
        message = "get instance match failed"
        logger.error(f"{message} => bill_cycle:{bill_cycle} page:{page} per_page:{per_page} field:{field} value:{value}")
        return resp_400(message)
    return resp_200(result)



@router.get('/instance/account/', summary="获取账单数据, 根据公司/账号聚合", description="云账单-账单可视化")
async def get_bill_instance_account(bill_cycle: str = Query(..., description="账期"),
                               page: int = Query(1, ge=1), per_page: int = Query(10, ge=0),
                               db: Session = Depends(get_db), user=Depends(permission_checker)):
    bill_instance_handler = BillInstanceHandler()
    result = bill_instance_handler.get_instance_account(db, bill_cycle, page, per_page)
    if not result:
        message = "get instance account failed"
        logger.error(f"{message} => bill_cycle:{bill_cycle} page:{page} per_page:{per_page}")
        return resp_400(message)
    return resp_200(result)


@router.get('/instance/aggregate/', summary="获取账单数据, 根据field字段聚合", description="云账单-账单可视化")
async def get_bill_instance_aggregate(bill_cycle: str = Query(..., description="账期"),
                               field: BillInstanceGroupBy = Query(..., description="根据字段聚合"),
                               page: int = Query(1, ge=1), per_page: int = Query(10, ge=0),
                               db: Session = Depends(get_db), user=Depends(permission_checker)):
    bill_instance_handler = BillInstanceHandler()
    result = bill_instance_handler.get_instance_aggregate(db, bill_cycle, field, page, per_page)
    if not result:
        message = "get instance aggregate failed"
        logger.error(f"{message} => bill_cycle:{bill_cycle} field:{field} page:{page} per_page:{per_page}")
        return resp_400(message)
    return resp_200(result)




@router.get('/instance/cluster/year/', summary="获取某一集群,整年每个月的费用", description="云账单-账单可视化")
async def get_bill_instance_cluster_year(year: str = Query(None, description="查询的年份, 默认为本年"),
                               bill_class: BillInstanceClassCluster = Query(..., description="分账类型"),
                               db: Session = Depends(get_db), user=Depends(permission_checker)):
    bill_class_map = {
        "k8s-cluster": "k8s集群",
        "db-cluster": "数据库集群",
        "bigdata-offline-cluster": "大数据离线集群",
        "bigdata-realtime-cluster": "大数据实时集群"
    }
    bill_class = bill_class_map[bill_class]
    bill_instance_handler = BillInstanceHandler()
    result = bill_instance_handler.get_instance_cluster_year(db, year, bill_class)
    if not result:
        message = "get instance cluster year failed"
        logger.error(f"{message} => year:{year} bill_class:{bill_class}")
        return resp_400(message)
    return resp_200(result)


@router.get('/instance/cluster/', summary="获取账单数据, 根据集群分类，再按部门聚合", description="云账单-账单可视化")
async def get_bill_instance_cluster(bill_cycle: str = Query(..., description="账期"),
                               bill_class: BillInstanceClassCluster = Query(..., description="分账类型"),
                               page: int = Query(1, ge=1), per_page: int = Query(10, ge=0),
                               db: Session = Depends(get_db), user=Depends(permission_checker)):
    bill_class_map = {
        "k8s-cluster": "k8s集群",
        "db-cluster": "数据库集群",
        "bigdata-offline-cluster": "大数据离线集群",
        "bigdata-realtime-cluster": "大数据实时集群"
    }
    bill_class = bill_class_map[bill_class]
    bill_instance_handler = BillInstanceHandler()
    result = bill_instance_handler.get_instance_cluster(db, bill_cycle, bill_class, page, per_page)
    if not result:
        message = "get instance cluster failed"
        logger.error(f"{message} => bill_cycle:{bill_cycle} bill_class:{bill_class} page:{page} per_page:{per_page}")
        return resp_400(message)
    return resp_200(result)





@router.get('/instance/environment/', summary="获取账单数据, 根据环境分类，再按部门聚合", description="云账单-账单可视化")
async def get_bill_instance_environment(bill_cycle: str = Query(..., description="账期"),
                               bill_env: BillInstanceEnvironment = Query(..., description="环境"),
                               page: int = Query(1, ge=1), per_page: int = Query(10, ge=0),
                               db: Session = Depends(get_db), user=Depends(permission_checker)):
    bill_env_map = {
        "development": "测试环境",
        "production": "生产环境",
    }
    environment = bill_env_map[bill_env]
    bill_instance_handler = BillInstanceHandler()
    result = bill_instance_handler.get_instance_environment(db, bill_cycle, environment, page, per_page)
    if not result:
        message = "get instance env failed"
        logger.error(f"{message} => bill_cycle:{bill_cycle} environment:{environment} page:{page} per_page:{per_page}")
        return resp_400(message)
    return resp_200(result)



@router.post('/instance/task/', summary="启动同步阿里云账单的异步任务", description="云账单-账单可视化")
async def post_bill_instance_task(data: PostInstanceTask, db: Session = Depends(get_db), user=Depends(permission_checker)):
    bill_instance_handler = BillInstanceHandler()
    bill_cycle = data.dict()["bill_cycle"]
    result = bill_instance_handler.start_sys_task(db, bill_cycle)
    if not result:
        message = "start sys task failed"
        logger.error(f"{message} => bill_cycle:{bill_cycle}")
        return resp_400(message)
    return resp_200(result)








#### 账单分析表的操作 ####
@router.get('/analysis/', summary="获取对比账单数据, 根据表字段-模糊查询", description="云账单-账单可视化")
async def get_bill_analysis_search(bill_cycle: str = Query(..., description="账期"), field: str = Query("all"), value: str = Query(""),
                               page: int = Query(1, ge=1), per_page: int = Query(10, ge=0),
                               db: Session = Depends(get_db), user=Depends(permission_checker)):
    bill_analysis_handler = BillAnalysisHandler()
    result = bill_analysis_handler.get_analysis_search(db, bill_cycle, page, per_page, field, value)
    if not result:
        message = "get analysis search failed"
        logger.error(f"{message} => bill_cycle:{bill_cycle} page:{page} per_page:{per_page} field:{field} value:{value}")
        return resp_400(message)
    return resp_200(result)



@router.get('/analysis/match/', summary="获取对比账单数据, 根据表字段-完全查询", description="云账单-账单可视化")
async def get_bill_analysis_match(bill_cycle: str = Query(..., description="账期"),
                             field: str = Query(..., description="查询的字段"), value: str = Query(..., description="查询的值"),
                             page: int = Query(1, ge=1), per_page: int = Query(10, ge=0),
                             db: Session = Depends(get_db), user=Depends(permission_checker)):
    bill_analysis_handler = BillAnalysisHandler()
    result = bill_analysis_handler.get_analysis_match(db, bill_cycle, page, per_page, field, value)
    if not result:
        message = "get analysis match failed"
        logger.error(f"{message} => bill_cycle:{bill_cycle} page:{page} per_page:{per_page} field:{field} value:{value}")
        return resp_400(message)
    return resp_200(result)



@router.get('/analysis/summary/', summary="获取费用变更摘要", description="云账单-账单可视化")
async def get_bill_analysis_summary(bill_cycle: str = Query(..., description="账期"), db: Session = Depends(get_db), user=Depends(permission_checker)):
    bill_analysis_handler = BillAnalysisHandler()
    result = bill_analysis_handler.get_text_information(db, bill_cycle)
    if not result:
        message = "get analysis summary failed"
        logger.error(f"{message} => bill_cycle:{bill_cycle} ")
        return resp_400(message)
    return resp_200(result)



@router.get('/analysis/aggregate/', summary="获取对比账单数据, 根据表字段聚合", description="云账单-账单可视化")
async def get_bill_analysis_aggregate(bill_cycle: str = Query(..., description="账期"),
                               field: BillAnalysisGroupBy = Query(..., description="根据字段聚合"),
                               page: int = Query(1, ge=1), per_page: int = Query(10, ge=0),
                               db: Session = Depends(get_db), user=Depends(permission_checker)):
    bill_analysis_handler = BillAnalysisHandler()
    result = bill_analysis_handler.get_analysis_aggregate(db, bill_cycle, field, page, per_page)
    if not result:
        message = "get analysis aggregate failed"
        logger.error(f"{message} => bill_cycle:{bill_cycle} field:{field} page:{page} per_page:{per_page}")
        return resp_400(message)
    return resp_200(result)






#### 账单月度信息表操作 ####
@router.get('/month/', summary="获取账单月度数据, 根据表字段-模糊查询", description="云账单-账单可视化")
async def get_bill_month_search(field: str = Query("all", description="查询的字段名称"), value: str = Query("", description="字段值"),
                              page: int = Query(1, ge=1), per_page: int = Query(10, ge=0),
                              db: Session = Depends(get_db), user=Depends(permission_checker)):
    bill_month_handler = BillMonthHandler()
    result = bill_month_handler.get_month_search(db, page, per_page, field, value)
    if not result:
        message = "get bill month search failed"
        logger.error(f"{message} => page:{page} per_page:{per_page} field:{field} value:{value}")
        return resp_400(message)
    return resp_200(result)


@router.get('/month/match/', summary="获取账单月度数据, 根据表字段-完全查询", description="云账单-账单可视化")
async def get_bill_month_match(field: str = Query(..., description="查询的字段名称"), value: str = Query(..., description="字段值"),
                              page: int = Query(1, ge=1), per_page: int = Query(10, ge=0),
                              db: Session = Depends(get_db), user=Depends(permission_checker)):
    bill_month_handler = BillMonthHandler()
    result = bill_month_handler.get_month_match(db, page, per_page, field, value)
    if not result:
        message = "get bill month match failed"
        logger.error(f"{message} => page:{page} per_page:{per_page} field:{field} value:{value}")
        return resp_400(message)
    return resp_200(result)


@router.get('/month/year/', summary="获取一整年的月度账单信息", description="云账单-账单可视化")
async def get_bill_month_year(year: str = Query(None, description="查询的年份, 默认为本年"), db: Session = Depends(get_db), user=Depends(permission_checker)):
    bill_month_handler = BillMonthHandler()
    result = bill_month_handler.get_one_year(db, year)
    if not result:
        message = "get bill year failed"
        logger.error(f"{message} => year:{year} ")
        return resp_400(message)
    return resp_200(result)




@router.post('/budget/', summary="增加单个月度预算信息", description="云账单-账单可视化")
async def post_bill_month(data: PostBillMonth, db: Session = Depends(get_db), user=Depends(permission_checker)):
    bill_month_handler = BillMonthHandler()
    result = bill_month_handler.add_month(db, data.dict())
    if not result:
        message = "post bill month failed"
        logger.error(f"{message} => data:{data.dict()}")
        return resp_400(message)
    return resp_200()



@router.post('/budget/batch/', summary="增加批量月度预算信息, 给初始化数据使用", description="云账单-账单可视化")
async def post_bill_month_batch(data: List[PostBillMonth], db: Session = Depends(get_db), user=Depends(permission_checker)):
    bill_month_handler = BillMonthHandler()
    for month_data in data:
        result = bill_month_handler.add_month(db, month_data.dict())
        if not result:
            message = "post bill month batch failed"
            logger.error(f"{message} => data:{month_data.dict()}")
            return resp_400(message)
    return resp_200()



@router.put('/budget/', summary="修改单个月度预算信息", description="云账单-账单可视化")
async def put_bill_month(data: PutBillMonth, db: Session = Depends(get_db), user=Depends(permission_checker)):
    bill_month_handler = BillMonthHandler()
    result = bill_month_handler.update_month(db, data.dict())
    if not result:
        message = "put bill month failed"
        logger.error(f"{message} => data:{data.dict()}")
        return resp_400(message)
    return resp_200()



@router.delete('/month/', summary="删除账单月度信息", description="云账单-账单可视化")
async def delete_bill_month(data: DelBaseModel, db: Session = Depends(get_db), user=Depends(permission_checker)):
    bill_month_handler = BillMonthHandler()
    result = bill_month_handler.delete_month(db, data.dict())
    if not result:
        message = "delete bill month failed"
        logger.error(f"{message} => data:{data.dict()}")
        return resp_400(message)
    return resp_200()



#### 标签与公司信息的关系操作 ####
@router.get('/tag/department/', summary="获取标签信息, 根据表字段-模糊匹配", description="云账单-账单可视化")
async def get_bill_tag_department_search(field: str = Query("all", description="查询的字段名称"), value: str = Query("", description="字段值"),
                              page: int = Query(1, ge=1), per_page: int = Query(10, ge=0),
                              db: Session = Depends(get_db), user=Depends(permission_checker)):
    tag_department_handler = TagDepartmentHandler()
    result = tag_department_handler.get_tag_department_search(db, page, per_page, field, value)
    if not result:
        message = "get tag department search failed"
        logger.error(f"{message} => page:{page} per_page:{per_page} field:{field} value:{value}")
        return resp_400(message)
    return resp_200(result)


@router.get('/tag/department/match/', summary="获取标签信息, 根据表字段-完全匹配", description="云账单-账单可视化")
async def get_bill_tag_department_match(field: str = Query(..., description="查询的字段名称"), value: str = Query(..., description="字段值"),
                              page: int = Query(1, ge=1), per_page: int = Query(10, ge=0),
                              db: Session = Depends(get_db), user=Depends(permission_checker)):
    tag_department_handler = TagDepartmentHandler()
    result = tag_department_handler.get_tag_department_match(db, page, per_page, field, value)
    if not result:
        message = "get tag department match failed"
        logger.error(f"{message} => page:{page} per_page:{per_page} field:{field} value:{value}")
        return resp_400(message)
    return resp_200(result)


@router.post('/tag/department/', summary="增加标签信息", description="云账单-账单可视化")
async def post_bill_tag_department(data: PostTagDepartment, db: Session = Depends(get_db), user=Depends(permission_checker)):
    tag_department_handler = TagDepartmentHandler()
    result = tag_department_handler.add_tag_department(db, data.dict())
    if not result:
        message = "post tag department failed"
        logger.error(f"{message} => data:{data.dict()}")
        return resp_400(message)
    return resp_200()


@router.put('/tag/department/', summary="修改标签信息", description="云账单-账单可视化")
async def put_bill_tag_department(data: PutTagDepartment, db: Session = Depends(get_db), user=Depends(permission_checker)):
    tag_department_handler = TagDepartmentHandler()
    result = tag_department_handler.update_tag_department(db, data.dict())
    if not result:
        message = "put tag department failed"
        logger.error(f"{message} => data:{data.dict()}")
        return resp_400(message)
    return resp_200()


@router.delete('/tag/department/', summary="删除标签信息", description="云账单-账单可视化")
async def delete_bill_tag_department(data: DelBaseModel, db: Session = Depends(get_db), user=Depends(permission_checker)):
    tag_department_handler = TagDepartmentHandler()
    result = tag_department_handler.delete_tag_department(db, data.dict())
    if not result:
        message = "delete tag department failed"
        logger.error(f"{message} => data:{data.dict()}")
        return resp_400(message)
    return resp_200()













#### 资产事件的操作 ####
@router.get('/event/', summary="获取资产事件信息, 根据表字段-模糊匹配", description="云账单-账单可视化")
async def get_bill_event_search(field: str = Query("all", description="查询的字段名称"), value: str = Query("", description="字段值"),
                              page: int = Query(1, ge=1), per_page: int = Query(10, ge=0),
                              db: Session = Depends(get_db), user=Depends(permission_checker)):
    bill_event_handler = BillEventHandler()
    status, result = bill_event_handler.get_event_search(db, page, per_page, field, value)
    if not status:
        message = "get bill event search failed"
        logger.error(f"{message} => page:{page} per_page:{per_page} field:{field} value:{value}")
        return resp_400(message)
    return resp_200(result)


@router.get('/event/match/', summary="获取资产事件信息, 根据表字段-完全匹配", description="云账单-账单可视化")
async def get_bill_event_match(field: str = Query(..., description="查询的字段名称"), value: str = Query(..., description="字段值"),
                              page: int = Query(1, ge=1), per_page: int = Query(10, ge=0),
                              db: Session = Depends(get_db), user=Depends(permission_checker)):
    bill_event_handler = BillEventHandler()
    status, result = bill_event_handler.get_event_match(db, page, per_page, field, value)
    if not status:
        message = "get bill event match failed"
        logger.error(f"{message} => page:{page} per_page:{per_page} field:{field} value:{value}")
        return resp_400(message)
    return resp_200(result)



@router.get('/event/item/', summary="获取资产事件信息, 根据信息条目", description="云账单-账单可视化")
async def get_bill_event_item(bill_cycle: str = Query("", description="账期"), 
                              cloud_platform: str = Query("", description="云平台"),
                              info_type: str = Query("", description="信息类别"),
                              info_item: str = Query(..., description="信息条目"),
                              page: int = Query(1, ge=1), per_page: int = Query(10, ge=0),
                              db: Session = Depends(get_db), user=Depends(permission_checker)):
    bill_event_handler = BillEventHandler()
    status, result = bill_event_handler.get_event_item(db, bill_cycle, cloud_platform, info_type, info_item)
    if not status:
        message = "get bill event item failed"
        logger.error(f"{message} => bill_cycle:{bill_cycle} cloud_platform:{cloud_platform} info_type:{info_type} info_item:{info_item}")
        return resp_400(message)
    return resp_200(result)


@router.post('/event/', summary="增加资产事件信息", description="云账单-账单可视化")
async def post_bill_event(data: PostBillEvent, db: Session = Depends(get_db), user=Depends(permission_checker)):
    bill_event_handler = BillEventHandler()
    result = bill_event_handler.add_event(db, data.dict())
    if not result:
        message = "post bill event failed"
        logger.error(f"{message} => data:{data.dict()}")
        return resp_400(message)
    return resp_200()


@router.put('/event/', summary="修改资产事件信息", description="云账单-账单可视化")
async def put_bill_event(data: PutBillEvent, db: Session = Depends(get_db), user=Depends(permission_checker)):
    bill_event_handler = BillEventHandler()
    result = bill_event_handler.update_event(db, data.dict())
    if not result:
        message = "put bill event failed"
        logger.error(f"{message} => data:{data.dict()}")
        return resp_400(message)
    return resp_200()


@router.delete('/event/', summary="删除资产事件信息", description="云账单-账单可视化")
async def delete_bill_event(data: DelBaseModel, db: Session = Depends(get_db), user=Depends(permission_checker)):
    bill_event_handler = BillEventHandler()
    result = bill_event_handler.delete_event(db, data.dict())
    if not result:
        message = "delete bill event failed"
        logger.error(f"{message} => data:{data.dict()}")
        return resp_400(message)
    return resp_200()


@router.post('/event/workorder/task/', summary="启动同步工单信息的异步任务", description="云账单-账单可视化")
async def post_bill_event_workorder_task(data: PostBillEventWorkOrderTask, db: Session = Depends(get_db), user=Depends(permission_checker)):
    bill_event_handler = BillEventHandler()
    result = bill_event_handler.post_bill_event_workorder_task(db, data.dict())
    if not result:
        message = "start workorder task failed"
        logger.error(f"{message} => data:{data.dict()}")
        return resp_400(message)
    return resp_200(result)